package com.tc.picturesynthesis.first.util;


import com.google.zxing.*;
import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.common.HybridBinarizer;
import com.google.zxing.qrcode.QRCodeReader;
import com.google.zxing.qrcode.QRCodeWriter;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import com.tc.picturesynthesis.first.domain.UserInfo;
import net.coobird.thumbnailator.Thumbnails;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.nio.file.Path;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;

import static com.tc.picturesynthesis.first.util.PicSynthesisUtil.DEFAULT_BDVIEW;
import static com.tc.picturesynthesis.first.util.PicSynthesisUtil.DEFAULT_IMG_BASEURL;

/**
 * 二维码生成图片，保存到项目根目录
 * @author tc
 */
public class QrCodeUtil {
	private static final Logger log = LoggerFactory.getLogger(QrCodeUtil.class);

	private static final int QRCOLOR = 0xFF000000; // 默认是黑色
	private static final int BGWHITE = 0xFFFFFFFF; // 背景颜色

	/**
     * 谷歌 - 生成包含字符串信息的二维码图片
     * @param outputStream 文件输出流路径
     * @param content 二维码携带信息
     * @param qrCodeSize 二维码图片大小
     * @param imageFormat 二维码的格式
     * @throws WriterException
     * @throws IOException
     */
    public static boolean createQrCodeByZX(OutputStream outputStream, String content, int qrCodeSize, String imageFormat) throws WriterException, IOException{
            //设置二维码纠错级别ＭＡＰ
            Hashtable<EncodeHintType, ErrorCorrectionLevel> hintMap = new Hashtable();
            hintMap.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.L);  // 矫错级别
            QRCodeWriter qrCodeWriter = new QRCodeWriter();
            //创建比特矩阵(位矩阵)的QR码编码的字符串
            BitMatrix byteMatrix = qrCodeWriter.encode(content, BarcodeFormat.QR_CODE, qrCodeSize, qrCodeSize, hintMap);
            // 使BufferedImage勾画QRCode  (matrixWidth 是行二维码像素点)
            int matrixWidth = byteMatrix.getWidth();
            BufferedImage image = new BufferedImage(matrixWidth-200, matrixWidth-200, BufferedImage.TYPE_INT_RGB);
            image.createGraphics();
            Graphics2D graphics = (Graphics2D) image.getGraphics();
            graphics.setColor(Color.WHITE);
            graphics.fillRect(0, 0, matrixWidth, matrixWidth);
            // 使用比特矩阵画并保存图像
            graphics.setColor(Color.BLACK);
            for (int i = 0; i < matrixWidth; i++){
                for (int j = 0; j < matrixWidth; j++){
                    if (byteMatrix.get(i, j)){
                        graphics.fillRect(i-100, j-100, 1, 1);
                    }
                }
            }
            return ImageIO.write(image, imageFormat, outputStream);
    }



    /**
     * 谷歌 - 读二维码并输出携带的信息
     */
    public static void readQrCodeByZX(InputStream inputStream) throws IOException{
        //从输入流中获取字符串信息
        BufferedImage image = ImageIO.read(inputStream);
        //将图像转换为二进制位图源
        LuminanceSource source = new BufferedImageLuminanceSource(image);
        BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
        QRCodeReader reader = new QRCodeReader();
        Result result = null ;
        try {
         result = reader.decode(bitmap);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 谷歌 - 可控大小的二维码生成  不带logo
     * @param qrPath 输出地址
     * @param imgSize 大小
     * @param content 内容
     * @return 返回是否成功
     */
    @SuppressWarnings({ "unchecked", "rawtypes" })
	public static boolean createZXCode (String qrPath,int imgSize,String content){
		//定义二维码内容参数
		HashMap hints = new HashMap();
		//设置字符集编码格式
		hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
		//设置容错等级，在这里我们使用M级别
		hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.M);
		//设置边框距
		hints.put(EncodeHintType.MARGIN, 2);

		//生成二维码
		try {
			//指定二维码内容
			BitMatrix bitMatrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, imgSize, imgSize,hints);

			//指定生成图片的保存路径
			Path file = new File(qrPath).toPath();
			//生成二维码
			MatrixToImageWriter.writeToPath(bitMatrix, "jpg", file);
			return true;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return true;
    }

    /**
	 * 用于设置QR二维码参数   (一个匿名内部类,设置了三个值)
 	 */
    private static Map<EncodeHintType, Object> hints = new HashMap<EncodeHintType, Object>() {
        private static final long serialVersionUID = 1L;
        {
            put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);// 设置QR二维码的纠错级别（H为最高级别）具体级别信息
            put(EncodeHintType.CHARACTER_SET, "utf-8");// 设置编码方式
            put(EncodeHintType.MARGIN, 0);
        }
    };

    /**
     * 谷歌 - 生成带logo的二维码
     * @param logoFileBuffer logo流
     * @param codeFile 二维码输出文件
     * @param content 内容
     * @param note 标记
     * @param size 图片大小
     * @return 返回是否成功
     */
    public static  boolean drawLogoQRCode(BufferedImage logoFileBuffer, File codeFile, String content, String note,int size) {
        BufferedImage image = new BufferedImage(size, size, BufferedImage.TYPE_INT_RGB);
        try {
            MultiFormatWriter multiFormatWriter = new MultiFormatWriter();
            // 参数顺序分别为：编码内容，编码类型，生成图片宽度，生成图片高度，设置参数
            BitMatrix bm = multiFormatWriter.encode(content, BarcodeFormat.QR_CODE, size, size, hints);

            // 开始利用二维码数据创建Bitmap图片，分别设为黑（0xFFFFFFFF）白（0xFF000000）两色
            for (int x = 0; x < size; x++) {
                for (int y = 0; y < size; y++) {
                    image.setRGB(x, y, bm.get(x, y) ? QRCOLOR : BGWHITE);
                }
            }

            int width = image.getWidth();
            int height = image.getHeight();
            // 构建绘图对象
            Graphics2D g = image.createGraphics();
            // 读取Logo图片
            BufferedImage logo = logoFileBuffer;
            // 开始绘制logo图片
            g.drawImage(logo, width * 1 / 3, height * 1 / 3, width * 1 / 3, height * 1 / 3, null);
            g.dispose();
            if(logo != null){
            	logo.flush();
            }
            image.flush();
            return ImageIO.write(image, "png", codeFile); // TODO
        } catch (Exception e) {
            e.printStackTrace();
        }
        return true;
    }

	private static BufferedImage getBufferedImageForURL(String filePath) throws IOException {
        /**
         * asBufferedImage() 返回BufferedImage
         */
        BufferedImage thumbnail = Thumbnails.of(new URL(filePath))
        		.scale(1)
        		.asBufferedImage();
        return thumbnail;

    }

	/**
	 * 获取生成的用户二维码地址
	 * @param user 用户
	 * @return 返回二维码地址
	 * @throws IOException
	 */
	public static Map<String,String> getUserQrImgURL(UserInfo user) throws IOException{
		Map<String,String> map = new HashMap<String,String>();
		String qrPath = new StringBuffer(DEFAULT_IMG_BASEURL).append(user.getUserId()).append(".jpg").toString();
		boolean createFlag;
		Integer sharedByUserId = user.getUserId();  //被邀请人的id
		String content = new StringBuffer(DEFAULT_BDVIEW).append(sharedByUserId).toString();

		if(new File(qrPath).exists()){
			map.put("qrPath", qrPath);
			map.put("qrCode", content);
			log.info("绑定跳转页面地址二维码存在: " + qrPath);
		}else{
			try {
				if(createZXCode(qrPath, 400, content)){
					map.put("qrPath", qrPath);
					map.put("qrCode", content);
		        	//log.info("绑定跳转页面地址二维码生成成功! 文件地址在:{}  " + qrPath);
		        }else{
		        	qrPath = null;
		        }
			} catch (Exception e) {
				log.error("邀请二维码生成报错!" + e.getMessage());
				return null;
			}
		}
		return map;
	}
}
